package mr

// 任务管理器

type TaskManager struct {
	// 计数
	Task_All_Cnt      int // 任务总数
	Task_Complete_Cnt int // 已经完成的任务总数

	// 发布计数器
	Counter_TaskID    int // TaskID全局计数器
	Counter_TaskRunID int // 运行时ID的全局计数器

	// 状态详细记录
	// Task_RunMap     map[int]bool // 正在运行中的任务 TaskID:bool
	Task_VisMap     map[int]bool // 记录任务是否完成 TaskID:bool
	Task_WaitPubMap map[int]Task // 等待发布的任务 TaskID:bool
	Task_WaitingMap map[int]Task // 已经发布等待完成的任务 TaskRunID:bool

	// 任务种类执行标记
	Running_TaskType int // 当前执行的任务的种类
}

// 初始化 - 初始化函数
func (tm *TaskManager) Init_Manager(runTaskType int) {
	// 计数初始化
	tm.Task_All_Cnt = 0
	tm.Task_Complete_Cnt = 0
	// 发布计数器初始化
	tm.Counter_TaskID = 1
	tm.Counter_TaskRunID = 1
	// 状态记录表初始化
	tm.Task_VisMap = make(map[int]bool)
	tm.Task_WaitPubMap = make(map[int]Task)
	tm.Task_WaitingMap = make(map[int]Task)
	// 任务种类执行标记初始化
	tm.Running_TaskType = runTaskType
}

// 初始化 - 预装载1个任务
func (tm *TaskManager) Init_LoadTask(tasktype int, taskfiles []TagFile) {
	// 类型不匹配
	if tasktype != tm.Running_TaskType {
		return
	}
	// 生成任务ID
	curTaskID := tm.Counter_TaskID
	tm.Counter_TaskID++ // 增加任务ID计数
	// tm.Task_RunMap[curTaskID] = false
	tm.Task_VisMap[curTaskID] = false
	// 生成任务记录实体
	task := Task{
		TaskType:  tasktype,
		TaskID:    curTaskID,
		TaskRunID: -1, // 运行时ID由发布函数赋值
		TaskFile:  taskfiles,
	}
	tm.Task_WaitPubMap[curTaskID] = task
	// 计数标记
	tm.Task_All_Cnt++ // 增加总任务数量
}

// 运行时 - 发布任务
func (tm *TaskManager) PubTask() *Task {
	// 挑选需要发布的任务
	for taskID, task := range tm.Task_WaitPubMap {
		// 获取运行时编码
		runID := tm.Counter_TaskRunID
		tm.Counter_TaskRunID++
		// 创建运行时任务
		pubTask := Task{
			TaskType:  task.TaskType,
			TaskID:    task.TaskID,
			TaskRunID: runID,
			TaskFile:  task.TaskFile,
		}
		// 从等待发布任务中删除
		delete(tm.Task_WaitPubMap, taskID)
		// 添加到运行时任务
		tm.Task_WaitingMap[runID] = pubTask
		// 返回任务
		return &pubTask
	}
	// 没有可以用于发布的任务
	return nil
}

// 运行时 - 任务删除:TaskRunID
func (tm *TaskManager) DeleteRunTask(taskRunID int) {
	if task, ok := tm.Task_WaitingMap[taskRunID]; ok {
		// 只有类型正确才能够删除
		if task.TaskType == tm.Running_TaskType {
			// 从等待表中删除
			delete(tm.Task_WaitingMap, taskRunID)
		}
	}
}

// 运行时 - 任务回退:TaskRunID
func (tm *TaskManager) PushBackRunTask(taskRunID int) {
	MrLoger.Printf("TaskPushBack: TaskRunID:%v", taskRunID)
	if task, ok := tm.Task_WaitingMap[taskRunID]; ok {
		// 构造任务记录
		pbTask := Task{
			TaskType:  task.TaskType,
			TaskID:    task.TaskID,
			TaskRunID: -1,
			TaskFile:  task.TaskFile,
		}
		// 判断类型是否正确
		if pbTask.TaskType != tm.Running_TaskType {
			return
		}
		// 从等待表中删除
		delete(tm.Task_WaitingMap, taskRunID)
		// 所属任务是否已经完成
		if tm.Task_VisMap[pbTask.TaskID] {
			return
		}
		// 是否已经存在于待发布表
		if _, ok := tm.Task_WaitPubMap[pbTask.TaskID]; ok {
			return
		}
		// 添加到待发布表
		MrLoger.Printf("TaskPushBack: [ReAdd] TaskRunID:%v", taskRunID)
		tm.Task_WaitPubMap[pbTask.TaskID] = pbTask
	}
}

// 运行时 - 完成任务 - 该函数的锁是由Master添加的
func (tm *TaskManager) CompleteTask(taskRunID int) bool {
	// 查看是否是等待队列中的任务
	if task, ok := tm.Task_WaitingMap[taskRunID]; ok {
		// 获取taskID
		taskID := task.TaskID
		// 从等待表中删除
		delete(tm.Task_WaitingMap, taskRunID)
		// 计数调整
		if !tm.Task_VisMap[taskID] {
			tm.Task_Complete_Cnt++
			tm.Task_VisMap[taskID] = true
		}
		return true
	}
	return false
}

// 运行时 - 查询某项任务是否完成
func (tm *TaskManager) isComplete(taskID int) bool {
	return tm.Task_VisMap[taskID]
}

// 运行时 - 是否完成所有任务
func (tm *TaskManager) Done() bool {
	return tm.Task_All_Cnt == tm.Task_Complete_Cnt
}
